/**
* Oxide
*
* Copyright (c) 2011 Dinosaur Kick Pty Ltd, All rights reserved.
*
* This source code is made available under the "Modified BSD" licensing arrangement.
* See license.txt for details.
*/
// ----------------------------------------------------------------------------
#include <string>
#include <boost/format.hpp>
#include <boost/progress.hpp>
// ----------------------------------------------------------------------------
#ifndef O2_STR_INC
#define O2_STR_INC
namespace o2 {
// ----------------------------------------------------------------------------

#define O2_CSTR_T(type, literal)	(::o2::detail::str_selector<type>::cstring(literal, L ## literal))
#define O2_STR_T(type, literal)		(::o2::detail::str_selector<type>::string(literal, L ## literal))
#define O2_FORMAT_T(type, literal)	(::o2::detail::str_selector<type>::format(literal, L ## literal))
#define O2_STR_ENUM_T(type, name)	case name: return ::o2::detail::str_selector<type>::cstring(#name, L ## #name)

#define O2_CSTR(literal)			O2_CSTR_T(string_type, literal)
#define O2_STR(literal)				O2_STR_T(string_type, literal)
#define O2_FORMAT(literal)			O2_FORMAT_T(string_type, literal)
#define O2_STR_ENUM(name)			O2_STR_ENUM_T(string_type, name)

// ----------------------------------------------------------------------------

template <typename IteratorT>
typename std::iterator_traits<IteratorT>::value_type join(const IteratorT& begin, const IteratorT& end, const typename std::iterator_traits<IteratorT>::value_type& separator)
{
	typedef typename std::iterator_traits<IteratorT>::value_type result_type;
	result_type result;
	if (begin != end)
	{
		IteratorT iter = begin;
		result = *iter;

		for (++iter; iter != end; ++iter)
			result += separator + *iter;
	}
	return result;
}

// ----------------------------------------------------------------------------
namespace detail {
// ----------------------------------------------------------------------------

template <typename CharT>
struct str_selector
{
	typedef std::basic_string<CharT> string_type;
	typedef boost::basic_format<typename string_type::value_type> format_type;

	static const char* cstring(const char* str, const wchar_t*)
		{ return str; }
	static string_type string(const char* str, const wchar_t*)
		{ return str; }
	static string_type string(char ch, wchar_t)
		{ return string_type(1, ch); }
	static format_type format(const char* str, const wchar_t*)
		{ return format_type(str); }
};

template <>
struct str_selector<wchar_t>
{
	typedef std::basic_string<wchar_t> string_type;
	typedef boost::basic_format<typename string_type::value_type> format_type;

	static const wchar_t* cstring(const char*, const wchar_t* str)
		{ return str; }
	static string_type string(const char*, const wchar_t* str)
		{ return str; }
	static string_type string(char, wchar_t ch)
		{ return string_type(1, ch); }
	static format_type format(const char*, const wchar_t* str)
		{ return format_type(str); }
};

template <typename CharT, typename TraitsT, typename AllocT>
struct str_selector<std::basic_string<CharT, TraitsT, AllocT> >
{
	typedef std::basic_string<CharT, TraitsT, AllocT> string_type;
	typedef boost::basic_format<typename string_type::value_type> format_type;

	static const CharT* cstring(const char* a, const wchar_t* b)
		{ return str_selector<CharT>::cstring(a, b); }
	static string_type string(const char* a, const wchar_t* b)
		{ return str_selector<CharT>::string(a, b); }
	static string_type string(char a, wchar_t b)
		{ return str_selector<CharT>::string(a, b); }
	static format_type format(const char* a, const wchar_t* b)
		{ return str_selector<CharT>::format(a, b); }
};

// ----------------------------------------------------------------------------
} // namespace detail
} // namespace o2
#endif // O2_STR_INC
// ----------------------------------------------------------------------------
